const router=require('koa-router')();
const koaBody=require('koa-body');
const path=require('path');
const crypto=require('crypto');
const fs=require('fs');
const events=require('events');
const config=require('../config/config');
const {uploadDir,characterLengthLimit:{reg:regCharacterLengthLimit}}=config;
const User=require('../models/index').User;
const checkNotLogin=require('../middlewares/checkNotLogin');
const redis=require('../models/redis.server.model');
const ipLimit=require('../middlewares/ipLimit');

router.get('/',checkNotLogin(),async ctx=>{
    await ctx.render('reg',{
        title:'注册',
        success:ctx.flash.success,
        error:ctx.flash.error,
        regCharacterLengthLimit
    });
});

router.post('/',checkNotLogin(),ipLimit({action:'reg'}),koaBody({
    multipart:true,
    formidable:{
        uploadDir:uploadDir,
        keepExtensions:true,
        onFileBegin:(name,file)=>{
            file.path=path.join(uploadDir,path.basename(file.path).replace('upload_',''));
        }
    }
}), async ctx=>{
    let e=new events(),{body}=ctx.request,{name,password,repeat,email}=body.fields,avatar=body.files.avatar/*上传域对象始终存在，即使没有上传任何文件(且会生成没有后缀的空文件)*/;
    e.on('invalid',msg=>{
        ctx.flash={error:msg};
        fs.unlink(path.join(uploadDir,path.basename(avatar.path)));
        ctx.redirect('back');
    });

    e.on('same',(flash,redirect)=>{
        ctx.flash=flash;
        fs.unlink(path.join(uploadDir,path.basename(avatar.path)));
        ctx.redirect(redirect);
    });

    if(!name)return e.emit('invalid','用户名未输入');
    if(/\W/.test(name))return e.emit('invalid','用户名非法(字母、数字、下划线)');
    if(name.length<regCharacterLengthLimit.name[0] || name.length>regCharacterLengthLimit.name[1])return e.emit('invalid',`用户名长度非法(${regCharacterLengthLimit.name[0]}~${regCharacterLengthLimit.name[1]})`);
    if(!password)return e.emit('invalid','密码未输入');
    if(password.length<regCharacterLengthLimit.password[0] || password.length>regCharacterLengthLimit.password[1])return e.emit('invalid',`密码长度非法(${regCharacterLengthLimit.password[0]}~${regCharacterLengthLimit.password[1]})`);
    if(!repeat)return e.emit('invalid','确认密码未输入');
    if(password!==repeat)return e.emit('invalid','密码不一致');
    if(!email)return e.emit('invalid','邮箱未输入');
    if(!/\w+@\w+\.\w+/.test(email))return e.emit('invalid','邮箱格式错误');
    if(!avatar.name)return e.emit('invalid','未选择头像');

    //未激活用户名和邮箱检测
    let same=await redis.getActivatedByName(name+'&'+email);
    if(same)return e.emit('same',{notify:`用户名已经注册，但未激活。<a href="/activate/${same}">激活邮件已经发送，请前往激活</a>`},'/notify');

    //已激活用户名和邮箱检测
    let count=await Promise.all([
        User.count({name}),
        User.count({email})
    ]);

    if(count[0] || count[1])return e.emit('same',{error:'用户名或邮箱已经注册'},'back');

    let newUser={
        id:crypto.createHash('md5').update(name+'&'+email).digest('hex'),
        name,
        password:crypto.createHash('md5').update([password,config.secret].join()).digest('hex'),
        email,
        avatar:path.basename(avatar.path),
        regTimeStr:new Date().toLocaleString()
    };

    //注册成功
    //--添加注册频率限制数据
    await redis.addLimit({action:'reg',id:ctx.request.ip});
    //--添加注册激活数据
    await redis.addActivated(newUser);

    ctx.flash={notify:`注册成功，<a href="/activate/${newUser.id}">激活邮件已经发送，请前往激活</a>`};
    ctx.redirect('/notify');
});

module.exports=router;